package com._21cn.framework.base.controller;

import com._21cn.framework.http.HttpRequestInfo;
import com._21cn.framework.utils.DatePropertyEditor;
import com._21cn.framework.utils.JsonEncoder;
import com._21cn.framework.utils.StringUtil;
import org.springframework.ui.ModelMap;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindingResult;
import org.springframework.validation.Validator;
import org.springframework.web.bind.ServletRequestDataBinder;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * Created by 司徒海富 on 2017/3/20.
 */
public class BaseController {

    public static final String QUERY_PARAM = "queryParam";
    public static final String JSON_ENCODER = "jsonEncoder";
    public static int DEFAULT_PAGE_NO = 1;
    public static int DEFAULT_PAGE_SIZE = 20;
    public static final String PAGE_NO_PARAM = "pageNo";
    public static final String PAGE_SIZE_PARAM = "pageSize";
    public static final DatePropertyEditor DEFAULT_DATE_EDITOR = new DatePropertyEditor("yyyy-MM-dd HH:mm:ss");

    /***
     * 通用获取ids
     * @param reqInfo
     * @param model
     * @return
     */
    public String getGetObjectIds(HttpRequestInfo reqInfo, ModelMap model) {
        boolean batchParam = false;
        StringBuilder objectIds = new StringBuilder();

        if( model.containsKey( "inIdList" )  ){
            objectIds.append( model.get( "inIdList" ) );
            batchParam = true;
        } else if( !StringUtil.isEmpty( reqInfo.getParameter( "inIds" ) )  ){
            objectIds.append( model.get( "inIds" ) );
            batchParam = true;
        }

        if( batchParam ){
            model.remove( "eqId" );
        } else if( !StringUtil.isEmpty( reqInfo.getParameter( "eqId" ) )  ){
            objectIds.append( model.get( "eqId" ) );
        }
        return objectIds.toString();
    }

    public static ServletRequestDataBinder initBinder( Object target ){
        String objectName = StringUtils.uncapitalize(target.getClass().getSimpleName());
        return new ServletRequestDataBinder(target, objectName);
    }

    public static BindingResult bind( HttpServletRequest request, Object target, ModelMap model, Validator... validators ) {
        ServletRequestDataBinder binder = initBinder(target);
        binder.registerCustomEditor( Date.class, DEFAULT_DATE_EDITOR );
        return bind( binder, request, target, model, validators );
    }

    public static BindingResult bind( ServletRequestDataBinder binder, HttpServletRequest request, Object target, ModelMap model, Validator... validators ) {
        binder.bind(request);
        BindingResult result = binder.getBindingResult();
        for( Validator validator: validators){
            if( validator != null ){
                validator.validate( target, result );
            }
        }
        if( result.hasErrors() ){
            String objectName = StringUtils.uncapitalize(target.getClass().getSimpleName());
            model.addAttribute( objectName, target );
            model.addAttribute( BindingResult.MODEL_KEY_PREFIX + objectName, result );
        }
        return result;
    }

    public static void setRequestModelMap(HttpServletRequest request, ModelMap model ){
        setRequestModelMap( request, model, false, null );
    }

    public static void setRequestModelMap(HttpServletRequest request, ModelMap model, boolean query ){
        setRequestModelMap( request, model, query, null );
    }

    /**
     * 将request中的有效参数保存到ModelMap中，并自动生成QueryParam参数，用于返回查询结果页面
     * @param request
     * @param model
     * @param query
     * @param jsonEncoding
     */
    public static void setRequestModelMap(HttpServletRequest request, ModelMap model, boolean query, String jsonEncoding ){
        Map<String, String[]> parameterMap = request.getParameterMap();

        StringBuilder sb = new StringBuilder();
        boolean and = false;
        String queryParam = null;
        for(Map.Entry<String, String[]> entry : parameterMap.entrySet()){
            String key = entry.getKey();
            String[] values = entry.getValue();

            if(values != null && values.length >0 ){
                if( QUERY_PARAM.equalsIgnoreCase( key ) && !StringUtil.isEmpty(values[0]) ){
                    queryParam = values[0];
                    continue;
                }

                List<String> list = new ArrayList<String>();
                for( String v : values ){
                    if( StringUtil.isEmpty( v ) )
                        continue;
                    list.add( v );
                    try {
                        v = URLEncoder.encode( v, request.getCharacterEncoding() );
                    }
                    catch( UnsupportedEncodingException e ) {
                        e.printStackTrace();
                    }
                    if( and )
                        sb.append( "&" );
                    else
                        and = true;
                    sb.append( key ).append( "=" ).append( v );
                }
                if( list.size() == 1 ){
                    if( key.endsWith( "List" ) && (key.startsWith( "in" ) || key.startsWith( "notIn" ) ) )
                        model.addAttribute( key, list );
                    else{
                        String v = list.get( 0 );
                        if( key.contains( "callback" ) ){
                            v = v.replaceAll( "<script.*</script>", "" ).replaceAll( "[\\(\\)'\\s\";=]", "" );
                        }
                        if( jsonEncoding != null ){
                            v = StringUtil.charsetConvert( v, request.getCharacterEncoding(), jsonEncoding );
                            v = StringUtil.gbk2iso( v );
                        }
                        model.addAttribute( key, v );
                    }
                }
                else if( list.size()>1 ){
                    model.addAttribute( key, list );
                }
            }
        }
        if( query || queryParam == null )
            queryParam = sb.toString();
        model.addAttribute( QUERY_PARAM, queryParam );

        if( query){
            model.addAttribute( JSON_ENCODER, JsonEncoder.getInstance() );
            if( parameterMap.get(PAGE_NO_PARAM) == null){
                model.addAttribute(PAGE_NO_PARAM, DEFAULT_PAGE_NO );
            }
            if( parameterMap.get(PAGE_SIZE_PARAM) == null){
                model.addAttribute(PAGE_SIZE_PARAM, DEFAULT_PAGE_SIZE );
            }
        }
    }
}
